import 'package:flutter/material.dart';
import 'package:flutter_demo/constants/constants.dart';
import 'package:flutter_demo/constants/http_response_code.dart';
import 'package:flutter_demo/environments/env.dart';
import 'package:flutter_demo/ui/graphQL_test/api/logger_link.dart';
import 'package:flutter_demo/ui/graphQL_test/model/http_response.dart';
import 'package:flutter_demo/utils/ToastUtils.dart';
import 'package:flutter_demo/utils/query_result_ext.dart';
import 'package:flutter_demo/utils/sp_util.dart';
import 'package:graphql_flutter/graphql_flutter.dart';

///@date:  2024/1/18
///@author:  ZhaoPing
///@description: graphHL 客户端

class GraphQLAPIClient {
  GraphQLClient client() {
    final HttpLink httpLink = HttpLink(
      Env.envConfig.graphQLUrl,
      defaultHeaders: {},
    );

    /// Auth link
    final AuthLink authLink = AuthLink(
      getToken: () => "Bearer ${SpUtil.getString(Constants.spTokenKey)}",
    );

    /// Link
    final Link _link = LoggerLink().concat(authLink).concat(httpLink);

    /// Policies
    /// - Remove cache
    final policies = Policies(
      fetch: FetchPolicy.networkOnly,
    );

    return GraphQLClient(
      cache: GraphQLCache(),
      link: _link,
      defaultPolicies: DefaultPolicies(
        watchQuery: policies,
        query: policies,
        mutate: policies,
      ),
    );
  }

  /// Start query
  Future<HttpBaseResponse<T>> query<T>(
      String queries,
      Map<String, dynamic>? variables,
      T Function(Map<String, dynamic> data) dataParser) async {
    showLoading();
    final WatchQueryOptions options = WatchQueryOptions(
      document: gql(queries),
      variables: variables ?? {},
      fetchResults: true,
      parserFn: dataParser,
    );
    var result = await client().query(options);
    hideLoading();
    if (result.hasException) {
      var resp = result.getErrorResponse<T>()!;
      ToastUtils.show(resp.message!);
      return result.getErrorResponse<T>()!;
    }
    var data = result.parserFn((result.data ?? {})) as T;
    return HttpBaseResponse(code: HttpResponseCode.success, data: data);
  }

  /// Start mutation
  Future<QueryResult> mutation(String queries) async {
    final MutationOptions options = MutationOptions(
      document: gql(queries),
    );
    return await client().mutate(options);
  }

  /// Handle exception
  void handleException(QueryResult queryResult) {
    if (queryResult.exception?.linkException is HttpLinkServerException) {
      HttpLinkServerException httpLink =
          queryResult.exception?.linkException as HttpLinkServerException;
      if (httpLink.parsedResponse?.errors?.isNotEmpty == true) {
        print(
            "::: GraphQL error message log: ${httpLink.parsedResponse?.errors?.first.message}");
      }
      return;
    }
    if (queryResult.exception?.linkException is NetworkException) {
      NetworkException networkException =
          queryResult.exception?.linkException as NetworkException;
      print("::: GraphQL error message log: ${networkException.message}");
      return;
    }
  }

  @override
  void showLoading({String loadingText = "请求中..."}) {
    // OneContextUtils.oneContext.showDialog(
    //     barrierColor: Colors.transparent,
    //     builder: (_) {
    //       ///TODO 可以参考HttpLoadingDialog类自定义dialog样式
    //       return HttpLoadingDialog(loadingText);
    //     });
  }

  @override
  void hideLoading() {
    // if (OneContextUtils.oneContext.hasDialogVisible) {
    //   OneContextUtils.oneContext.popDialog();
    // }
  }
}
